package com.gpframework.module.controller.order;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gpframework.common.annotation.Log;
import com.gpframework.common.config.GpframeworkConfig;
import com.gpframework.common.constant.Constants;
import com.gpframework.common.constant.HttpStatus;
import com.gpframework.common.core.controller.BaseController;
import com.gpframework.common.core.domain.AjaxResult;
import com.gpframework.common.core.domain.entity.SysDept;
import com.gpframework.common.core.domain.entity.SysRole;
import com.gpframework.common.core.page.TableDataInfo;
import com.gpframework.common.core.redis.RedisCache;
import com.gpframework.common.enums.*;
import com.gpframework.common.utils.DateUtils;
import com.gpframework.common.utils.ServletUtils;
import com.gpframework.common.utils.StringUtils;
import com.gpframework.common.utils.poi.ExcelUtil;
import com.gpframework.common.utils.spring.SpringUtils;
import com.gpframework.common.utils.uuid.IdUtils;
import com.gpframework.common.weixin.common.constants.WeiXinConstants;
import com.gpframework.common.weixin.common.message.base.AccessToken;
import com.gpframework.common.weixin.common.message.base.Template;
import com.gpframework.module.core.LoginUser;
import com.gpframework.module.order.domain.GpFlowConfig;
import com.gpframework.module.order.domain.GpOrder;
import com.gpframework.module.order.domain.GpOrderFlow;
import com.gpframework.module.order.domain.req.*;
import com.gpframework.module.order.domain.vo.DataVo;
import com.gpframework.module.order.domain.vo.GpHomeStatisticsVo;
import com.gpframework.module.order.domain.vo.GpOrderFlowVo;
import com.gpframework.module.order.domain.vo.GpOrderVo;
import com.gpframework.module.order.service.IGpFlowConfigService;
import com.gpframework.module.order.service.IGpOrderFlowService;
import com.gpframework.module.order.service.IGpOrderService;
import com.gpframework.module.order.service.IGpProductService;
import com.gpframework.module.service.TokenService;
import com.gpframework.module.system.mapper.SysDeptMapper;
import com.gpframework.module.system.mapper.SysRoleMapper;
import com.gpframework.module.system.mapper.SysUserMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName GpOrderController
 * @Author gpframework
 * @Date 2023-06-16
 * @Version 1.0.0
 * @Description 销售单Controller
 */
@Validated
@Api(tags = "销售单")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@SuppressWarnings({"rawtypes","unchecked"})
@RequestMapping("/order/order" )
public class GpOrderController extends BaseController {

    private final IGpOrderService iGpOrderService;
    private final IGpProductService gpProductService;
    private final IGpOrderFlowService gpOrderFlowService;
    private final IGpFlowConfigService gpFlowConfigService;
    private final SysUserMapper sysUserMapper;
    private final SysRoleMapper sysRoleMapper;
    private final SysDeptMapper sysDeptMapper;
    private final RedisCache redisCache;

    /**
     * @Description 分页
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
    */
    @ApiOperation("首页统计")
    //@PreAuthorize("@ss.hasPermi('order:order:list')")
    @GetMapping("/homeStatistics")
    public AjaxResult<GpHomeStatisticsVo> homeStatistics(GpOrderReq gpOrderReq)
    {

        LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
        Long userId = loginUser.getUser().getUserId();
        gpOrderReq.setIsUrgent(null);
        QueryWrapper<GpOrder> lqw = new QueryWrapper<GpOrder>();
        gpOrderReq.generatorQuery(lqw,true);
        // 获取用户角色权限标识
        List<SysRole> sysRoles = sysRoleMapper.selectRolePermissionByUserId(userId);
        boolean isAll = sysRoles.stream().anyMatch(role -> role.getDataScope().equals("1"));
        boolean isDept = sysRoles.stream().anyMatch(role -> role.getDataScope().equals("4"));
        if (!isAll) {
            if (isDept) {
                // 查部门订单
                SysDept sysDept = sysDeptMapper.selectDeptById(loginUser.getUser().getDeptId());
                lqw.eq("gp.organise_unit", sysDept.getDeptName());
            } else {
                // 查个人订单
                lqw.eq("gp.salesman", loginUser.getUser().getNickName());
            }
        }
        GpHomeStatisticsVo gpHomeStatisticsVo= iGpOrderService.homeStatistics(lqw);
        lqw.apply("DATE_FORMAT(gp.create_time, '%Y-%m-%d') = DATE_FORMAT(NOW(), '%Y-%m-%d')");
        GpHomeStatisticsVo todayHomeStatisticsVo = iGpOrderService.todayHomeStatistics(lqw);
        if (gpHomeStatisticsVo != null && todayHomeStatisticsVo != null) {
            gpHomeStatisticsVo.setTodayTotal(todayHomeStatisticsVo.getTodayTotal());
            gpHomeStatisticsVo.setTodayComplete(todayHomeStatisticsVo.getTodayComplete());
            gpHomeStatisticsVo.setTodayException(todayHomeStatisticsVo.getTodayException());
        }
        return AjaxResult.success(gpHomeStatisticsVo);
    }

    /**
     * @Description 超期订单列表
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
    */
    @ApiOperation("超期订单列表")
    //@PreAuthorize("@ss.hasPermi('order:order:list')")
    @GetMapping("/overdueOrderList")
    public TableDataInfo<GpOrderVo> overdueOrderList(GpOrderReq gpOrderReq)
    {
        startPage();
        List<GpOrderVo> list = iGpOrderService.overdueOrderList(gpOrderReq);
        return getDataTable(list);
    }

    /**
     * @Description 分页
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
    */
    @ApiOperation("列表")
    //@PreAuthorize("@ss.hasPermi('order:order:list')")
    @GetMapping("/list")
    public TableDataInfo<GpOrderVo> list(GpOrderReq gpOrderReq)
    {
        LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
        Long userId = loginUser.getUser().getUserId();
        QueryWrapper<GpOrder> lqw = new QueryWrapper<GpOrder>();
        if (gpOrderReq.getIsException() != null && gpOrderReq.getIsException() == 1) {
            // 如果查询的是异常单子，不过滤加急、验货
            gpOrderReq.setIsUrgent(null);
            gpOrderReq.setIsInspection(null);
        }
        gpOrderReq.generatorQuery(lqw,true);
        if (StringUtils.isBlank(gpOrderReq.getOrderStatus())) {
            // 列表查询不查已完成数据
            lqw.ne("gp.order_status", OrderStatusEnum.COMPLETE.getKey());
        }
        // 获取用户角色权限标识
        List<SysRole> sysRoles = sysRoleMapper.selectRolePermissionByUserId(userId);
        boolean isAll = sysRoles.stream().anyMatch(role -> role.getDataScope().equals("1"));
        boolean isDept = sysRoles.stream().anyMatch(role -> role.getDataScope().equals("4"));
        if (!isAll) {
            if (isDept) {
                // 查部门订单
                SysDept sysDept = sysDeptMapper.selectDeptById(loginUser.getUser().getDeptId());
                lqw.eq("gp.organise_unit", sysDept.getDeptName());
            } else {
                // 查个人订单
                lqw.eq("gp.salesman", loginUser.getUser().getNickName());
            }
        }
        if (gpOrderReq.getOperatorId() != null) {
            lqw.eq("gof.user_id", gpOrderReq.getOperatorId());
        }
//        lqw.groupBy("gp.id");
//        if (gpOrderReq.getOrderByCreateTime() != null && gpOrderReq.getOrderByCreateTime() == 1) {
//            lqw.orderByDesc("gp.create_time");
//        } else {
//            lqw.orderByDesc("gp.is_urgent");
//            lqw.orderByDesc("gp.is_exception");
//            lqw.orderByAsc("gp.is_cancel");
//            lqw.orderByAsc("gp.update_time");
//        }
        gpOrderReq.setEw(lqw);
        startPage();
        List<GpOrderVo> list = iGpOrderService.listVo(gpOrderReq);
        for (GpOrderVo gpOrderVo : list) {
            getOrderTime(gpOrderVo);
            gpOrderVo.setRemark(gpOrderVo.getRemark() + " " + gpOrderVo.getLinkManAndPhone());
        }
        return getDataTable(list);
    }

    /**
     * @Description 新增
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("新增")
    @PreAuthorize("@ss.hasPermi('order:order:add')" )
    @Log(title = "添加销售单" , businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Valid @RequestBody GpOrderAddMy gpOrderAddMy) {
        GpOrderAdd gpOrderAdd = Convert.convert(new TypeReference<GpOrderAdd>() {}, gpOrderAddMy);
        List<GpProductUpdate> gpProductUpdateList = new ArrayList<>();
        List<GpProductDetailsUpdate> gpProductDetailsUpdates = new ArrayList<>();
        for (GpProductAddMy gpProductAddMy : gpOrderAddMy.getProductList()) {
            gpProductDetailsUpdates = new ArrayList<>();
            GpProductUpdate gpProductUpdate = Convert.convert(new TypeReference<GpProductUpdate>() {}, gpProductAddMy);
            for (GpProductDetailsAddMy detail : gpProductAddMy.getDetails()) {
                GpProductDetailsUpdate gpProductDetailsUpdate = Convert.convert(new TypeReference<GpProductDetailsUpdate>() {}, detail);
                gpProductDetailsUpdates.add(gpProductDetailsUpdate);
            }
            gpProductUpdate.setDetails(gpProductDetailsUpdates);
            gpProductUpdateList.add(gpProductUpdate);
        }
        gpOrderAdd.setProductList(gpProductUpdateList);
        return iGpOrderService.collection(gpOrderAdd);
    }

    /**
     * @Description 修改
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("修改")
    @PreAuthorize("@ss.hasPermi('order:order:edit')" )
    @Log(title = "修改销售单" , businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Valid @RequestBody GpOrderUpdate gpOrderUpdate) {
        GpOrder gpOrder = Convert.convert(new TypeReference<GpOrder>() {}, gpOrderUpdate);
        if (gpOrder.getIsException() != null && gpOrder.getIsException() == 1) {
            gpOrder.setIsUrgent(0);
            gpOrder.setIsCancel(0);
        }
        if (gpOrder.getIsUrgent() != null && gpOrder.getIsUrgent() == 1) {
            gpOrder.setIsException(0);
            gpOrder.setIsCancel(0);
        }
        if (gpOrder.getIsCancel() != null && gpOrder.getIsCancel() == 1) {
            gpOrder.setIsException(0);
            gpOrder.setIsUrgent(0);
        }

        GpOrder order = iGpOrderService.getById(gpOrderUpdate.getId());
        if (order == null) {
            return AjaxResult.error("订单：" + gpOrderUpdate.getId() + "不存在；");
        }
        Date now = new Date();
        if (order.getIsException() == 0 && gpOrder.getIsException() != null && gpOrder.getIsException() == 1) {
            // 如果订单状态从正常改成异常，记录暂停开始时间
            gpOrder.setSuspendStartTime(now);
        } else if (order.getIsException() == 1 && gpOrder.getIsException() != null && gpOrder.getIsException() == 0) {
            // 如果订单状态从异常改成正常，记录暂停结束时间和暂停时长
            gpOrder.setSuspendEndTime(now);
            gpOrder.setSuspendDuration(DateUtils.getDateMinDiff(now, order.getSuspendStartTime()));
        }
        return toAjax(iGpOrderService.updateById(gpOrder) ? 1 : 0);
    }


    /**
     * @Description 批量完成
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("批量完成")
    @PreAuthorize("@ss.hasPermi('order:order:edit')" )
    @Log(title = "批量完成" , businessType = BusinessType.UPDATE)
    @PutMapping("/complete")
    public AjaxResult complete(@Valid @RequestBody GpOrderUpdate gpOrderUpdate) {
        if (CollectionUtils.isEmpty(gpOrderUpdate.getIds())) {
            return AjaxResult.error("缺少必要参数");
        }
        boolean update = iGpOrderService.update(new UpdateWrapper<GpOrder>().set("order_status", OrderStatusEnum.COMPLETE.getKey()).in("id", gpOrderUpdate.getIds()));
        return toAjax(update ? 1 : 0);
    }


    /**
     * @Description 导出
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("导出销售单")
    @PreAuthorize("@ss.hasPermi('order:order:export')" )
    @Log(title = "导出销售单" , businessType = BusinessType.EXPORT)
    @GetMapping("/export" )
    public AjaxResult export(GpOrderReq gpOrderReq) {
        LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
        Long userId = loginUser.getUser().getUserId();
        QueryWrapper<GpOrder> lqw = new QueryWrapper<GpOrder>();
        gpOrderReq.generatorQuery(lqw,true);
        if (StringUtils.isBlank(gpOrderReq.getOrderStatus())) {
            // 列表查询不查已完成数据
            lqw.ne("gp.order_status", OrderStatusEnum.COMPLETE.getKey());
        }
        // 获取用户角色权限标识
        List<SysRole> sysRoles = sysRoleMapper.selectRolePermissionByUserId(userId);
        boolean isAll = sysRoles.stream().anyMatch(role -> role.getDataScope().equals("1"));
        boolean isDept = sysRoles.stream().anyMatch(role -> role.getDataScope().equals("4"));
        if (!isAll) {
            if (isDept) {
                // 查部门订单
                SysDept sysDept = sysDeptMapper.selectDeptById(loginUser.getUser().getDeptId());
                lqw.eq("gp.organise_unit", sysDept.getDeptName());
            } else {
                // 查个人订单
                lqw.eq("gp.salesman", loginUser.getUser().getNickName());
            }
        }
        lqw.groupBy("gp.id");
        if (gpOrderReq.getOrderByCreateTime() != null && gpOrderReq.getOrderByCreateTime() == 1) {
            lqw.orderByDesc("gp.create_time");
        } else {
            lqw.orderByDesc("gp.is_urgent");
            lqw.orderByDesc("gp.is_exception");
            lqw.orderByAsc("gp.is_cancel");
            lqw.orderByAsc("gp.update_time");
        }
        List<GpOrderVo> list = iGpOrderService.listVo(lqw);
        ExcelUtil<GpOrderVo> util = new ExcelUtil<GpOrderVo>(GpOrderVo. class);
        return util.exportExcel(list, "order" );
    }

    /**
     * @Description 详情
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("详情")
    @PreAuthorize("@ss.hasPermi('order:order:query')" )
    @GetMapping(value = "/{id}" )
    public AjaxResult<GpOrderVo> getInfo(@PathVariable("id" ) Long id) {
        GpOrderVo gpOrderVo = iGpOrderService.getVoById(id);
        List<GpOrderFlowVo> orderFlowList = gpOrderFlowService.listVo(new QueryWrapper<GpOrderFlow>().eq("gp.order_id", id).eq("gp.del_status", YesNoEnum.NO.getKey()));
        for (GpOrderFlowVo gpOrderFlowVo : orderFlowList) {
            if (StringUtils.isNotBlank(gpOrderFlowVo.getAnnex())) {
                gpOrderFlowVo.setAnnexList(Arrays.asList(gpOrderFlowVo.getAnnex().split(",")));
            }
        }
        gpOrderVo.setOrderFlowList(orderFlowList);
        gpOrderVo.setProductList(gpProductService.productListByOrderId(gpOrderVo.getId()));
        getOrderTime(gpOrderVo);
        return AjaxResult.success(gpOrderVo);
    }

    private void getOrderTime(GpOrderVo gpOrderVo) {
        gpOrderVo.setProductList(gpProductService.productListByOrderId(gpOrderVo.getId()));
        GpOrderFlow orderFlow = gpOrderFlowService.getOne(new QueryWrapper<GpOrderFlow>().eq("order_id", gpOrderVo.getId()).eq("del_status", YesNoEnum.NO.getKey()).orderByDesc("create_time").last("limit 1"));
        if (orderFlow != null) {
            GpFlowConfig beforeFlowConfig = gpFlowConfigService.getById(orderFlow.getConfigId());
            GpFlowConfig flowConfig = gpFlowConfigService.getByOrderStatus(gpOrderVo.getOrderStatus());
            // 如果有订单跟进记录，且没有下一步
            if (flowConfig == null) {
                // 接入时间和到期时间使用最后一条跟进记录
                gpOrderVo.setInletTime(orderFlow.getInletTime());
                gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(orderFlow.getInletTime(), beforeFlowConfig.getRedDuration().intValue()));
                // TODO:LEE 散剪和大货流转时间区分先不开启，等前端将配置接上去再开
                if (StringUtils.equals(gpOrderVo.getOrderCharacteristics(), OrderCharacteristicsEnum.LOOSE_SHEAR.getKey())) {
                    gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(orderFlow.getInletTime(), beforeFlowConfig.getRedDuration().intValue()));
                } else {
                    gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(orderFlow.getInletTime(), beforeFlowConfig.getBigRedDuration().intValue()));
                }
                gpOrderVo.setFlowConfig(beforeFlowConfig);
            } else {
                // 接入时间和到期时间使用下一步时间计算
                gpOrderVo.setInletTime(orderFlow.getProcessingTime());
                gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(orderFlow.getProcessingTime(), flowConfig.getRedDuration().intValue()));
                // TODO:LEE 散剪和大货流转时间区分先不开启，等前端将配置接上去再开
                if (StringUtils.equals(gpOrderVo.getOrderCharacteristics(), OrderCharacteristicsEnum.LOOSE_SHEAR.getKey())) {
                    gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(orderFlow.getProcessingTime(), flowConfig.getRedDuration().intValue()));
                } else {
                    gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(orderFlow.getProcessingTime(), flowConfig.getBigRedDuration().intValue()));
                }
                gpOrderVo.setFlowConfig(flowConfig);
            }
        } else {
            gpOrderVo.setInletTime(gpOrderVo.getCreateTime());
            GpFlowConfig flowConfig = gpFlowConfigService.getOne(new QueryWrapper<GpFlowConfig>().eq("del_status", YesNoEnum.NO.getKey()).orderByAsc("sort").last("limit 1"));
            if (flowConfig != null) {
                gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(gpOrderVo.getCreateTime(), flowConfig.getRedDuration().intValue()));
                // TODO:LEE 散剪和大货流转时间区分先不开启，等前端将配置接上去再开
                if (StringUtils.equals(gpOrderVo.getOrderCharacteristics(), OrderCharacteristicsEnum.LOOSE_SHEAR.getKey())) {
                    gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(gpOrderVo.getCreateTime(), flowConfig.getRedDuration().intValue()));
                }else {
                    gpOrderVo.setExpirationTime(DateUtils.getAfterMinute(gpOrderVo.getCreateTime(), flowConfig.getBigRedDuration().intValue()));
                }
                gpOrderVo.setFlowConfig(flowConfig);
            }
        }
        if (gpOrderVo.getSuspendEndTime() != null) {
            gpOrderVo.setInletTime(gpOrderVo.getSuspendEndTime());
        }
    }



    /**
     * @Description 删除
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("删除")
    @PreAuthorize("@ss.hasPermi('order:order:remove')" )
    @Log(title = "删除销售单" , businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}" )
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(iGpOrderService.removeByIds(Arrays.asList(ids)) ? 1 : 0);
    }

    /**
     * @Description 订单采集
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("订单采集")
    @PreAuthorize("@ss.hasPermi('order:order:add')" )
    @Log(title = "订单采集" , businessType = BusinessType.INSERT)
    @PostMapping("/collection")
    public AjaxResult collection(@Valid @RequestBody GpOrderUpdate gpOrderUpdate) throws Exception {
        // 发送HTTP请求获取XML数据
//        orderCloudNumber = "69374584526019390105";
        String orderCloudNumber = gpOrderUpdate.getOrderCloudNumber();
        URL url = new URL("https://bch5.taobubao.com/api/H5PayService/OrderLetter/Entrance?Number=" + orderCloudNumber + "&from=1");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        ObjectMapper objectMapper = new ObjectMapper();
        try {
//            DataVo data = objectMapper.readValue(sb.toString(), DataVo.class);
            Map<String, Object> dataMap = objectMapper.readValue(sb.toString(), Map.class);
            if (dataMap == null) {
                return AjaxResult.error("获取不到订单信息");
            }
            DataVo data = initData(dataMap);

            if (data.getResultCode() != 200) {
                return AjaxResult.error(HttpStatus.CONFLICT,"获取订单状态异常：ResultCode=" + data.getResultCode());
            }
            if (StringUtils.isNotBlank(data.getOrderContent())) {
                Map<String, Object> map = objectMapper.readValue(data.getOrderContent(), Map.class);
                GpOrderAdd orderAdd = this.initOrder(map);
                if (orderAdd == null) {
                    return AjaxResult.error(HttpStatus.CONFLICT,"获取不到订单信息");
                }
                return iGpOrderService.collection(orderAdd);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.error(HttpStatus.CONFLICT,"录入失败");
    }

    private DataVo initData(Map<String, Object> dataMap) {
        DataVo dataVo = new DataVo();
        if (dataMap.get("ResultCode") != null) {
            dataVo.setResultCode(Integer.parseInt(dataMap.get("ResultCode").toString()));
        }
        if (dataMap.get("ResultMessage") != null) {
            dataVo.setResultMessage(dataMap.get("ResultMessage").toString());
        }
        if (dataMap.get("BrandName") != null) {
            dataVo.setBrandName(dataMap.get("BrandName").toString());
        }
        if (dataMap.get("H5PayQR64") != null) {
            dataVo.setH5PayQR64(dataMap.get("H5PayQR64").toString());
        }
        if (dataMap.get("InspectDetailEnable") != null) {
            dataVo.setInspectDetailEnable(Boolean.parseBoolean(dataMap.get("InspectDetailEnable").toString()));
        }
        if (dataMap.get("IsESEnable") != null) {
            dataVo.setIsESEnable(Boolean.parseBoolean(dataMap.get("IsESEnable").toString()));
        }
        if (dataMap.get("IsESSigned") != null) {
            dataVo.setIsESSigned(Boolean.parseBoolean(dataMap.get("IsESSigned").toString()));
        }
        if (dataMap.get("IsOfflineAccountEnable") != null) {
            dataVo.setIsOfflineAccountEnable(Boolean.parseBoolean(dataMap.get("IsOfflineAccountEnable").toString()));
        }
        if (dataMap.get("IsPaid") != null) {
            dataVo.setIsPaid(Boolean.parseBoolean(dataMap.get("IsPaid").toString()));
        }
        if (dataMap.get("IsPayEnable") != null) {
            dataVo.setIsPayEnable(Boolean.parseBoolean(dataMap.get("IsPayEnable").toString()));
        }
        if (dataMap.get("OrderContent") != null) {
            dataVo.setOrderContent(dataMap.get("OrderContent").toString());
        }
        if (dataMap.get("OrderID") != null) {
            dataVo.setOrderID(Long.parseLong(dataMap.get("OrderID").toString()));
        }
        if (dataMap.get("OrderNumber") != null) {
            dataVo.setOrderNumber(dataMap.get("OrderNumber").toString());
        }
        if (dataMap.get("OrderType") != null) {
            dataVo.setOrderType(Integer.parseInt(dataMap.get("OrderType").toString()));
        }
        if (dataMap.get("PayDiscount") != null) {
            dataVo.setPayDiscount(dataMap.get("PayDiscount").toString());
        }
        if (dataMap.get("PayingSource") != null) {
            dataVo.setPayingSource(Integer.parseInt(dataMap.get("PayingSource").toString()));
        }
        if (dataMap.get("WechatPayEnable") != null) {
            dataVo.setWechatPayEnable(Boolean.parseBoolean(dataMap.get("WechatPayEnable").toString()));
        }
        return dataVo;
    }


    private GpOrderAdd initOrder(Map<String, Object> map)  throws Exception {
        GpOrderAdd gpOrderAdd = new GpOrderAdd();
        if (map.get("FormName") != null) {
            gpOrderAdd.setFormName(map.get("FormName").toString());
        }
        if (map.get("OrganiseUnit") != null) {
            gpOrderAdd.setOrganiseUnit(map.get("OrganiseUnit").toString());
        }
        if (map.get("FormType") != null) {
            gpOrderAdd.setFormType(Long.parseLong(map.get("FormType").toString()));
        }
        if (map.get("ClientName") != null) {
            gpOrderAdd.setClientName(map.get("ClientName").toString());
        }
        if (map.get("FormCode") != null) {
            gpOrderAdd.setFormCode(map.get("FormCode").toString());
        }
        if (map.get("ExpectPayment") != null) {
            gpOrderAdd.setExpectPayment(map.get("ExpectPayment").toString());
        }
        if (map.get("TotalBranchesQuantity") != null) {
            gpOrderAdd.setTotalBranchesQuantity(map.get("TotalBranchesQuantity").toString());
        }
        if (map.get("TotalQuantity") != null) {
            gpOrderAdd.setTotalQuantity(map.get("TotalQuantity").toString());
        }
        if (map.get("TotalPostQuantity") != null) {
            gpOrderAdd.setTotalPostQuantity(map.get("TotalPostQuantity").toString());
        }
        if (map.get("Freight") != null) {
            gpOrderAdd.setFreight(map.get("Freight").toString());
        }
        if (map.get("Remark") != null) {
            gpOrderAdd.setRemark(map.get("Remark").toString());
        }
        if (map.get("LinkManAndPhone") != null) {
            gpOrderAdd.setLinkManAndPhone(map.get("LinkManAndPhone").toString());
        }
        if (map.get("Address") != null) {
            gpOrderAdd.setAddress(map.get("Address").toString());
        }
        if (map.get("IsValid") != null) {
            gpOrderAdd.setValid(Boolean.parseBoolean(map.get("IsValid").toString()));
        }
        if (map.get("IsShowBatchNO") != null) {
            gpOrderAdd.setShowBatchNo(Boolean.parseBoolean(map.get("IsShowBatchNO").toString()));
        }
        if (map.get("IsShowFreight") != null) {
            gpOrderAdd.setShowFreight(Boolean.parseBoolean(map.get("IsShowFreight").toString()));
        }
        if (map.get("IsShowRemark") != null) {
            gpOrderAdd.setShowRemark(Boolean.parseBoolean(map.get("IsShowRemark").toString()));
        }
        if (map.get("IsShowLinkManAndPhone") != null) {
            gpOrderAdd.setShowLinkManAndPhone(Boolean.parseBoolean(map.get("IsShowLinkManAndPhone").toString()));
        }
        if (map.get("IsShowAddress") != null) {
            gpOrderAdd.setShowAddress(Boolean.parseBoolean(map.get("IsShowAddress").toString()));
        }
        if (map.get("IsShowPostQuantity") != null) {
            gpOrderAdd.setShowPostQuantity(Boolean.parseBoolean(map.get("IsShowPostQuantity").toString()));
        }
        if (map.get("IsShowPrice") != null) {
            gpOrderAdd.setShowPrice(Boolean.parseBoolean(map.get("IsShowPrice").toString()));
        }
        if (map.get("AdjustAmount") != null) {
            gpOrderAdd.setAdjustAmount(map.get("AdjustAmount").toString());
        }
        if (map.get("AdvanceAmount") != null) {
            gpOrderAdd.setAdvanceAmount(map.get("AdvanceAmount").toString());
        }
        if (map.get("CollectingAmount") != null) {
            gpOrderAdd.setCollectingAmount(map.get("CollectingAmount").toString());
        }
        if (map.get("PaidInOrOut") != null) {
            gpOrderAdd.setPaidInOrOut(map.get("PaidInOrOut").toString());
        }
        if (map.get("OrderBalance") != null) {
            gpOrderAdd.setOrderBalance(map.get("OrderBalance").toString());
        }
        if (map.get("OrderCloudNumber") != null) {
            gpOrderAdd.setOrderCloudNumber(map.get("OrderCloudNumber").toString());
        }
        if (map.get("Merchandiser") != null) {
            gpOrderAdd.setSalesman(map.get("Merchandiser").toString());
        }
        Object productList = map.get("ProductList");
        if (productList != null) {
            ObjectMapper mapper = new ObjectMapper();
            List<GpProductUpdate> productAddList = mapper.convertValue(productList, new com.fasterxml.jackson.core.type.TypeReference<List<GpProductUpdate>>(){});
            if (CollectionUtils.isNotEmpty(productAddList)) {
                productAddList.forEach(gpProductUpdate -> gpProductUpdate.setId(null));
                gpOrderAdd.setProductList(productAddList);
            }
        }
        return gpOrderAdd;
    }

    /**
     * @Description 生成订单号
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("生成订单号")
    @PreAuthorize("@ss.hasPermi('order:order:query')" )
    @GetMapping(value = "/generateFormCode/{type}" )
    public AjaxResult generateFormCode(@PathVariable("type" ) String type) {
        StringBuilder formCode = new StringBuilder();
        if (StringUtils.isBlank(type)) {
            return AjaxResult.error("缺少必要参数[type]");
        }
        if (StringUtils.equals(type, FormTypeEnum.SALES_SLIP.getKey())) {
            formCode.append("GBD-");
        }
        if (StringUtils.equals(type, FormTypeEnum.PROCESSING_OUTBOUND_ORDER.getKey())) {
            formCode.append("ED-");
        }
        if (StringUtils.equals(type, FormTypeEnum.PURCHASE_RETURN.getKey())) {
            formCode.append("AE-");
        }
        if (StringUtils.equals(type, FormTypeEnum.TRANSFER_OUT_ORDER.getKey())) {
            formCode.append("CD-");
        }
        String yyyyMMdd = DateUtils.getDate("yyyyMMdd");
        formCode.append(yyyyMMdd);
        formCode.append("-");
        Integer codeNum = redisCache.getCacheObject("code" + yyyyMMdd);
        if (codeNum == null) {
            codeNum = 1;
        } else {
            codeNum ++;
        }
        redisCache.setCacheObject("code" + yyyyMMdd, codeNum, 24, TimeUnit.HOURS);
        String codeNumStr = String.valueOf(codeNum);
        if (codeNumStr.length() < 4) {
            int length = 4 - codeNumStr.length();
            for (int i = 0; i < length; i++) {
                codeNumStr = "0" + codeNumStr;
            }
        }
        formCode.append(codeNumStr);
        return AjaxResult.success(formCode.toString());
    }

    /**
     * @Description 补打二维码
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("补打二维码")
    @PreAuthorize("@ss.hasPermi('order:order:query')" )
    @GetMapping(value = "/printQrCodeAgain/{id}" )
    public AjaxResult<GpOrderVo> printQrCodeAgain(@PathVariable("id" ) Long id) {
        GpOrder gpOrder = iGpOrderService.getById(id);
        String date = DateUtils.datePath();
        String uuid = IdUtils.fastUuid();
        String filePath = GpframeworkConfig.getUploadPath() + "/" + date + "/" + uuid + ".jpg";
        File file = FileUtil.file(filePath);
        if (!file.exists()) {
            // 文件不存在，创建新文件
            FileUtil.touch(file);
        }
        QrCodeUtil.generate(gpOrder.getOrderCloudNumber() + "?50-" + gpOrder.getOrderCloudNumber(), 300, 300, file);
        gpOrder.setOrderQrCode(Constants.RESOURCE_PREFIX + "/upload/" + date + "/" + uuid + ".jpg");
        iGpOrderService.updateById(gpOrder);
        return AjaxResult.success(gpOrder.getOrderQrCode());
    }

    /**
     * @Description 暂停/取消暂停
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return AjaxResult
     */
    @ApiOperation("暂停/取消暂停")
    @PreAuthorize("@ss.hasPermi('order:order:edit')" )
    @PostMapping("/suspend")
    public AjaxResult suspend(@Valid @RequestBody GpOrderUpdate gpOrderUpdate) {
        if (gpOrderUpdate == null || CollectionUtils.isEmpty(gpOrderUpdate.getIds()) || gpOrderUpdate.getIsSuspend() == null) {
            return AjaxResult.error("缺少必要参数");
        }
        StringBuilder returnStr = new StringBuilder();
        Date now = new Date();
        for (Long id : gpOrderUpdate.getIds()) {
            GpOrder gpOrder = iGpOrderService.getById(id);
            if (gpOrder == null) {
                returnStr.append("订单：").append(id).append("不存在；");
                continue;
            }
            if (gpOrder.getIsSuspend() == 0 && gpOrderUpdate.getIsSuspend() == 0) {
                returnStr.append("订单：").append(gpOrder.getFormCode()).append("未暂停，无法取消暂停；");
                continue;
            } else if (gpOrder.getIsSuspend() == 1 && gpOrderUpdate.getIsSuspend() == 1) {
                returnStr.append("订单：").append(gpOrder.getFormCode()).append("已暂停，无需暂停；");
                continue;
            } else if (gpOrderUpdate.getIsSuspend() == 1) {
                gpOrder.setIsSuspend(gpOrderUpdate.getIsSuspend());
                gpOrder.setSuspendStartTime(now);
            } else {
                gpOrder.setIsSuspend(gpOrderUpdate.getIsSuspend());
                gpOrder.setSuspendEndTime(now);
                gpOrder.setSuspendDuration(DateUtils.getDateMinDiff(now, gpOrder.getSuspendStartTime()));
            }
            iGpOrderService.updateById(gpOrder);
        }
        if (StringUtils.isNotBlank(returnStr.toString())) {
            return AjaxResult.error(510, returnStr.toString());
        }
        return AjaxResult.success();
    }

    /**
     * @Description 异常--欠货
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return AjaxResult
     */
    @ApiOperation("异常--欠货")
    @PreAuthorize("@ss.hasPermi('order:order:edit')" )
    @PostMapping("/outOfStock")
    public AjaxResult outOfStock(@Valid @RequestBody GpOrderUpdateMy gpOrderUpdate) {
        return toAjax(iGpOrderService.outOfStock(gpOrderUpdate) ? 1 : 0);
    }

    /**
     * @Description 发送公众号消息
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return AjaxResult
     */
    @ApiOperation("发送公众号消息")
    @GetMapping("/message")
    public AjaxResult message(String openId) {
        AccessToken accessToken = new AccessToken();
        String requestUrl = WeiXinConstants.ACCESS_TOKEN_URL.replace("APPID", WeiXinConstants.WX_APP_ID).replace("APPSECRET", WeiXinConstants.WX_APP_SECRET);
        String requestStr = HttpUtil.get(requestUrl);
        if (!org.springframework.util.StringUtils.isEmpty(requestStr)) {
            accessToken = JSONUtil.toBean(requestStr, AccessToken.class);
            if (accessToken.getErrcode() != null) {

            }
        }
        if (StringUtils.isNull(accessToken) || StringUtils.isBlank(accessToken.getAccess_token())) {
            return AjaxResult.error("accessToken为空" );
        }

        return AjaxResult.success(sendOfficialAccountMsg(accessToken, openId));
    }

    /**
     * 发送公众号通知
     * @param accessToken
     * @return
     */
    private String sendOfficialAccountMsg(AccessToken accessToken, String openId) {
        Template template = Template.New()
                .setMiniprogram_state("formal") // developer为开发版: trial为体验版:formal为正式版，默认为正式版
                .setLang("zh_CN")
                // openid
                .setTouser(openId)
                .setPage("/pack-user/report/index");
        template.setTemplate_id("nrULpU5PhOLa7PH6gz6oQf9z3I3Y-LkElIeAPUkouYg");
        template.add("thing9", "您的每日报表已生成，可点击查看详情");
        template.add("time6", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()));
        template.addMiniprogram("appid", WeiXinConstants.APP_ID);
        template.addMiniprogram("pagepath", "/pack-user/report/index?time="+DateUtils.parseDateToStr("yyyy-MM-dd", new Date()));
        String body = HttpRequest.post(WeiXinConstants.APP_ADVANCED_SUBSCRIBE_SEND_URL + accessToken.getAccess_token())
                .body(template.build())
                .execute().body();
        return body;
    }

    /**
     * @Description 大屏订单列表
     * @Author gpframework
     * @Date 2023-06-16
     * @Param gpOrder
     * @Return TableDataInfo
     */
    @ApiOperation("大屏订单列表")
    @GetMapping("/largeScreenList")
    public TableDataInfo<GpOrderVo> largeScreenList(GpOrderReq gpOrderReq)
    {
        if (StringUtils.isBlank(gpOrderReq.getOrderStatus())) {
            return getError("缺少必要字段[订单状态]");
        }
        startPage();
        List<GpOrderVo> list = iGpOrderService.largeScreenList(gpOrderReq.getOrderStatus());
        return getDataTable(list);
    }
}
